#include "libkyprocess.h"
#include <cstring-extension.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <linux/param.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <locale.h>
#include <sys/stat.h>

#define PRG_SOCKET_PFX    "socket:["
#define PRG_SOCKET_PFXl (strlen(PRG_SOCKET_PFX))
#define PRG_SOCKET_PFX2   "[0000]:"
#define PRG_SOCKET_PFX2l  (strlen(PRG_SOCKET_PFX2))

#define LINE_MAX 4096

#define COLWID 240 
#define UPTIME_FILE  "/proc/uptime"
#define MEMINFO					"/proc/meminfo"
#define MAX_PF_NAME				1024
#define PROC_DIR                "/proc"
#define MAX_PROC_NUM            1024
#define PROC_NUM                500
#define BUF_SIZE 1024
static int uptime_fd = -1;
#define LC_NUMERIC        __LC_NUMERIC
#define __LC_NUMERIC		 1
static char buf[8192];
#define O_RDONLY	     00
#define BAD_OPEN_MESSAGE					\
"Error: /proc must be mounted\n"				\
"  To mount /proc at boot you need an /etc/fstab line like:\n"	\
"      proc   /proc   proc    defaults\n"			\
"  In the meantime, run \"mount proc /proc -t proc\"\n"

#define FILE_TO_BUF(filename, fd) do{				\
    static int local_n;						\
    if (fd == -1 && (fd = open(filename, O_RDONLY)) == -1) {	\
	fputs(BAD_OPEN_MESSAGE, stderr);			\
	fflush(NULL);						\
	_exit(102);						\
    }								\
    lseek(fd, 0L, SEEK_SET);					\
    if ((local_n = read(fd, buf, sizeof buf - 1)) < 0) {	\
	perror(filename);					\
	fflush(NULL);						\
	_exit(103);						\
    }								\
    buf[local_n] = '\0';					\
}while(0)

#define SET_IF_DESIRED(x,y) do{  if(x) *(x) = (y); }while(0)

struct pstat {
	long unsigned int utime_ticks;
	long unsigned int stime_ticks;
	long unsigned int cpu_total_time;
};

/* 进程信息 */
typedef struct process_info
{
    long proc_pid; //进程id
    char proc_name[128]; //进程名
    char proc_command[4096]; //进程启动的命令行,包含启动参数
    char proc_uid[128]; //进程所属用户　用户uid
    char start_time[128]; //进程启动的时间 (char * ctime(time_t time) 函数返回值Tue Jul 28 08:50:26 2020)
    unsigned long utime; //进程cpu使用时间,单位s
    double proc_cpu; //进程cpu使用率 %
    double proc_mem; //进程mem使用量 %
    char proc_state[20]; //进程状态
    char proc_time[20]; //进程运行时间
    char proc_port[20];  //进程端口号
       
} process_info;

#define PROCESS_ITEM 14
#define PROC_COMD_NUM 11520
 
typedef struct {
	unsigned long user;
	unsigned long nice;
	unsigned long system;
	unsigned long idle;
}Total_Cpu_Occupy_t;
 
 
typedef struct {
	unsigned int pid;
	unsigned long utime;  //user time
	unsigned long stime;  //kernel time
	unsigned long cutime; //all user time
        unsigned long cstime; //all dead time
}Proc_Cpu_Occupy_t;

static unsigned long lookup_num(char* buffer, const char* key, unsigned long *res)
{
    if (strstartswith(buffer, key) == 0)
    {
        char *val = buffer;
        val += strlen(key) + 1;
        *res = atol(strskipblank(val));
        return 1;
    }
    return 0;
}

static int lookup(char *line, char *pattern, char **value)
{
	char *p, *v;
	int len = strlen(pattern);

	/* pattern */
	if (strncmp(line, pattern, len))
		return 0;

	/* white spaces */
	for (p = line + len; isspace(*p); p++);

	/* separator */
	if (*p != ':')
		return 0;

	/* white spaces */
	for (++p; isspace(*p); p++);

	/* value */
	if (!*p)
		return 0;
	v = p;

	/* end of value */
	len = strlen(line) - 1;
	for (p = line + len; isspace(*(p-1)); p--);
	*p = '\0';

	*value = strdup(v);
	return 1;
}

static int isnumber(char *c)
{
	char *i = c;

	while(*i != '\0') {
		if (!isdigit(*i))
			return 0;
		i++;
	}
	return 1;
}

static size_t strlcpy(char *dst, const char *src, size_t siz)
{
	char *d = dst;
	const char *s = src;
	size_t n = siz;

	/* Copy as many bytes as will fit */
	if (n != 0 && --n != 0) {
		do {
			if ((*d++ = *s++) == 0)
				break;
		} while (--n != 0);
	}

	/* Not enough room in dst, add NUL and traverse rest of src */
	if (n == 0) {
		if (siz != 0)
			*d = '\0';              /* NUL-terminate dst */
		while (*s++)
			;
	}

	return (s - src - 1);    /* count does not include NUL */
}

//获取第N项开始的指针
const char* get_items(const char*buffer ,unsigned int item){
	
	const char *p =buffer;
 
	int len = strlen(buffer);
	int count = 0;
	
	for (int i=0; i<len;i++){
		if (' ' == *p){
			count ++;
			if(count == item -1){
				p++;
				break;
			}
		}
		p++;
	}
 
	return p;
}
 
 
//获取总的CPU时间
unsigned long get_cpu_total_occupy(){
	
	FILE *fd;
	char buff[1024]={0};
	Total_Cpu_Occupy_t t;
 
	fd =fopen("/proc/stat","r");
	if (!fd){
		return 0;
	}
		
	fgets(buff,sizeof(buff),fd);
	char name[64]={0};
	sscanf(buff,"%s %ld %ld %ld %ld",name,&t.user,&t.nice,&t.system,&t.idle);
	fclose(fd);
	
	return (t.user + t.nice + t.system + t.idle);
}
 
 
//获取进程的CPU时间
unsigned long get_cpu_proc_occupy(unsigned int pid){
	
	char file_name[64]={0};
	Proc_Cpu_Occupy_t t;
	FILE *fd;
	char line_buff[1024]={0};
	sprintf(file_name,"/proc/%d/stat",pid);
	
	fd = fopen(file_name,"r");
	if(!fd){
		return 0;
	}
	
	fgets(line_buff,sizeof(line_buff),fd);
	
	sscanf(line_buff,"%u",&t.pid);
	const char *q =get_items(line_buff,PROCESS_ITEM);
	sscanf(q,"%ld %ld %ld %ld",&t.utime,&t.stime,&t.cutime,&t.cstime);
	fclose(fd);
	
	return (t.utime + t.stime + t.cutime + t.cstime);
}

float kdk_get_process_cpu_usage_percent(int proc_num)
{
    unsigned long totalcputime1,totalcputime2;
	unsigned long procputime1,procputime2;
	
	totalcputime1=get_cpu_total_occupy();
	procputime1=get_cpu_proc_occupy(proc_num);
 
	usleep(200000);
 
	totalcputime2=get_cpu_total_occupy();
	procputime2=get_cpu_proc_occupy(proc_num);
	
	float pcpu = 0.0;
	if(0 != totalcputime2-totalcputime1){ 
		pcpu=100.0 * (procputime2-procputime1)/(totalcputime2-totalcputime1);
	}

	return pcpu;
}

float kdk_get_process_mem_usage_percent(int proc_num)
{
    char path[100] = {0};
    char *name = NULL;
    float percent = 0.00;
    unsigned long memTotal = 0, memRSS = 0;
    sprintf(path, "/proc/%d/status", proc_num);

    FILE *fp = fopen(path, "rt");
    if (!fp)
        return 0.00;
    
    char buffer[1025];
    char buffers[1025];

    while (fgets(buffer, 1024, fp))
    {
        if (lookup_num(buffer, "VmRSS", &memRSS))
            break;
    }

    FILE *fb = fopen(MEMINFO, "rt");
    if (!fp)
        return 0.00;
    while (fgets(buffers, 1024, fb))
    {
        if (lookup_num(buffers, "MemTotal", &memTotal))
            break;
    }
    if (memTotal)
        percent = ((float)memRSS / (float)memTotal)*100;

    fclose(fp);

    return percent;
}

char *kdk_get_process_status(int proc_num)
{
    char path[100] = {0};
    char *name = NULL;
    sprintf(path, "/proc/%d/status", proc_num);

    FILE *fp = fopen(path, "rt");
    if (!fp)
        return NULL;
    
    char buffer[1025];

    while (fgets(buffer, 1024, fp))
    {
        if (lookup(buffer, "State", &name))
            break;
    }

    fclose(fp);

    return name;
}

static int extract_type_1_socket_inode(const char lname[], unsigned long * inode_p) {

    /* If lname is of the form "socket:[12345]", extract the "12345"
       as *inode_p.  Otherwise, return -1 as *inode_p.
       */
    
    if (lname[strlen(lname)-1] != ']') return -1;

    {
        char inode_str[strlen(lname + 1)];  /* e.g. "12345" */
        const int inode_str_len = strlen(lname) - PRG_SOCKET_PFXl - 1;
        char *serr;

        strncpy(inode_str, lname+PRG_SOCKET_PFXl, inode_str_len);
        inode_str[inode_str_len] = '\0';
        *inode_p = strtoul(inode_str, &serr, 0);
        if (!serr || *serr || *inode_p == ~0)
            return -1;
    }
    return 0;
}

static int extract_type_2_socket_inode(const char lname[], unsigned long * inode_p) {

    /* If lname is of the form "[0000]:12345", extract the "12345"
       as *inode_p.  Otherwise, return -1 as *inode_p.
       */

    if (strlen(lname) < PRG_SOCKET_PFX2l+1) return -1;
    if (memcmp(lname, PRG_SOCKET_PFX2, PRG_SOCKET_PFX2l)) return -1;
    {
        char *serr;
        *inode_p = strtoul(lname + PRG_SOCKET_PFX2l, &serr, 0);
        if (!serr || *serr || *inode_p == ~0)
            return -1;
    }
    return 0;
}

int kdk_get_process_port(int proc_num)
{
    unsigned long rxq, txq, time_len, retr, inode;
    int num, local_port, rem_port, d, state, uid, timer_run, timeout;
    char rem_addr[128], local_addr[128], timers[64];
	char file_name[100] = {0};
	FILE *fd;
	char line_buff[1024]={0};
    char line[LINE_MAX];
    int lnamelen;
    char lname[30];
    unsigned long inode_num;
    DIR *dirfd = NULL;
    struct dirent *direproc, *direfd;
    char path[100] = {0};
    sprintf(path, "/proc/%d/fd", proc_num);

	dirfd = opendir(path);
    if (! dirfd) {
	    return 0;
	}
	while ((direfd = readdir(dirfd))) {
        sprintf(line, "/proc/%d/fd/%s", proc_num, direfd->d_name);
	    lnamelen = readlink(line, lname, sizeof(lname) - 1);
	    if (lnamelen == -1)
		    continue;
        lname[lnamelen] = '\0';  /*make it a null-terminated string*/

        if (extract_type_1_socket_inode(lname, &inode_num) < 0)
            if (extract_type_2_socket_inode(lname, &inode_num) < 0)
                continue;
        fd = fopen("/proc/net/tcp","r");
        if(NULL == fd){
            return 0;
        }
        
        while(fgets(line_buff,sizeof(line_buff),fd))
        {
            num = sscanf(line_buff,
            "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %lu %*s\n",
                    &d, local_addr, &local_port, rem_addr, &rem_port, &state,
                    &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode);
            if(inode_num == inode)
            {
                return local_port;
            }else
            {
                continue;
            }
        }
    }
}

char* kdk_get_process_start_time(int proc_num)
{
    char path[100] = {0};
    char *name = (char *)calloc(128, sizeof(char));
	char *t = NULL;
	char tt[1024] = {0};
	unsigned long long time1, starttime;
	char *st = NULL;

    sprintf(path, "/proc/%d/stat", proc_num);

	FILE *fpstat = fopen(path, "r");
	if (fpstat == NULL) {
		return NULL;
	}

	t = fgets(tt, sizeof(tt), fpstat);
	if (sscanf(t , "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %*u %*u %*d %*d %*d %*d %*d %*d %19llu %*u", &time1) == EOF) {
		fclose(fpstat);
		return NULL;
	}
	fclose(fpstat);
	time_t now;
	now = time(NULL);
	struct timespec time2 = {0, 0};
	clock_gettime(CLOCK_MONOTONIC, &time2);

	starttime = (unsigned long long)(time1/HZ) + (now - time2.tv_sec);
    
	time_t time3 = starttime;
	st = (char *)calloc(128, sizeof(char));

	st = ctime(&time3);
	strncpy(name, st, 128);
    return name;
}

int uptime(double *restrict uptime_secs, double *restrict idle_secs) {
    double up=0, idle=0;
    char *savelocale;

    FILE_TO_BUF(UPTIME_FILE,uptime_fd);
    savelocale = strdup(setlocale(LC_NUMERIC, NULL));
    setlocale(LC_NUMERIC,"C");
    if (sscanf(buf, "%lf %lf", &up, &idle) < 2) {
        setlocale(LC_NUMERIC,savelocale);
        free(savelocale);
        fputs("bad data in " UPTIME_FILE "\n", stderr);
	    return 0;
    }
    setlocale(LC_NUMERIC,savelocale);
    free(savelocale);
    SET_IF_DESIRED(uptime_secs, up);
    SET_IF_DESIRED(idle_secs, idle);
    return up;	/* assume never be zero seconds in practice */
}

char* kdk_get_process_running_time(int proc_num)
{
    char path[100] = {0};
	char *t = NULL;
	char tt[1024] = {0};
	unsigned long long time1, starttime;
	char *st = NULL;
    unsigned long long seconds;

    sprintf(path, "/proc/%d/stat", proc_num);
	FILE *fpstat = fopen(path, "r");
	if (fpstat == NULL) {
		return NULL;
	}

	t = fgets(tt, sizeof(tt), fpstat);
	if (sscanf(t , "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %*u %*u %*d %*d %*d %*d %*d %*d %19llu %*u", &time1) == EOF) {
		fclose(fpstat);
		return NULL;
	}
	fclose(fpstat);
    
    time_t seconds_since_boot    = uptime(0,0);
    seconds = seconds_since_boot - (time1/100);
    char *restrict const outbuf;
    
    unsigned dd,hh,mm,ss;
    char *cp = (char *)calloc(128, sizeof(char));
    char *buff = (char *)calloc(128, sizeof(char));
    ss = seconds%60;
    seconds /= 60;
    mm = seconds%60;
    seconds /= 60;
    hh = seconds%24;
    seconds /= 24;
    dd = seconds;
    if(dd)
    {
        snprintf(cp, COLWID, "%u-", dd);
    }else{
        snprintf(cp, COLWID, "%u-", 0);
    }
    if(dd || hh)
    {
        snprintf(buff, COLWID, "%02u:", hh);
        strcat(cp, buff);
    }
    else{
        snprintf(buff, COLWID, "%02u:", 0);
        strcat(cp, buff);
    }
    memset(buff,'\0',sizeof(buff));
    snprintf(buff, COLWID, "%02u:%02u", mm, ss);
    strcat(cp, buff);
    free(buff);
    return cp;
}

char* kdk_get_process_cpu_time(int proc_num)
{
    char path[100] = {0};
	struct pstat result;
	unsigned long utime = 0;
    char *name = (char *)calloc(128, sizeof(char));

    sprintf (path, "/proc/%d/stat", proc_num);

	FILE *fpstat = fopen(path, "r");
	if (fpstat == NULL) {
		return NULL;
	}

	//read values from /proc/pid/stat
	bzero(&result, sizeof(struct pstat));

	if (fscanf(fpstat, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu %*s",
		   &result.utime_ticks, &result.stime_ticks) == EOF) {
		fclose(fpstat);
		return NULL;
	}

	utime = (long)((result.utime_ticks + result.stime_ticks)/HZ);
    sprintf(name, "%ld秒", utime);
	fclose(fpstat);

	return name;
}

char* kdk_get_process_command(int proc_num)
{
    FILE *fd;
	char path[128] = {0};
    char *command = (char *)malloc(1024 * sizeof(char));
    char line[1024] = {0};

	if (proc_num < 0 )
		return NULL;
	else
		sprintf(path, "/proc/%d/cmdline", proc_num);

	if (strstr(path, "../"))
		return NULL;

	if ((fd = fopen(path, "r")) == NULL) {
		return NULL;
	}
    
	int c;
	int i =0;
	while(1) {
		char a = ' ';
        
		c = fgetc(fd);
		if (feof(fd))
			break;
		if (c == '\0')
			line[i] = a;
		else
			line[i] = c;
		i++;
	}
    strcpy(command, line);

	fclose(fd);
    return command;
}

char* kdk_get_process_user(int proc_num)
{
    FILE *fpprocstat, *fp;
	char procstatf[128] = {0};
	char line[128] = {0};
    char buff[128] = {0};
    char *name = NULL;
    int j = 0, i = 0;
    char *bufs[10], *q = NULL;
    char *buf[5], *p = NULL;

    sprintf (procstatf, "/proc/%d/status", proc_num);


	if ((fpprocstat = fopen(procstatf, "r")) == NULL)
		return NULL;

	while (fgets(line, sizeof(line), fpprocstat) != NULL) {
		if (lookup(line, "Uid", &name))
            break;
	}

	p = strtok(name, "	");
	while(p)
	{
		buf[i] = p;
		i++;
		p = strtok(NULL,"	");
	}
    if ((fp = fopen("/etc/passwd", "r")) == NULL)
		return NULL;

	while (fgets(buff, sizeof(buff), fp) != NULL) {
		if(strstr(buff, buf[1]))
        {
            q = strtok(buff, ":");
            while(q)
            {
                bufs[j] = q;
                j++;
                q = strtok(NULL,":");
            }
            
            if(!strcmp(buf[1],bufs[2]))
            {
                strcpy(name, bufs[0]);
                break;
            }
        }
	}

	fclose(fpprocstat);
    fclose(fp);

	return name;
}

int** getPidByName(char *task_name)
{
    DIR *dir;
    struct dirent *ptr;
    FILE *fp;
    char path[50];
    char cur_task_name[50];
    char buf[BUF_SIZE];
    int i = 0;
    int **res = NULL;
    int **ret = realloc(res, sizeof(int)*500);
    res = ret;
    
    dir = opendir("/proc");
    if(NULL != dir)
    {
         while ((ptr = readdir(dir)) != NULL) //循环读取/proc下的每一个文件/文件夹
         {
            res[i] = malloc(sizeof(int) * 500);
             //如果读取到的是"."或者".."则跳过，读取到的不是文件夹名字也跳过
             if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0))
                 continue;
             if (DT_DIR != ptr->d_type)
                 continue;
            
             sprintf(path, "/proc/%s/status", ptr->d_name);//生成要读取的文件的路径
             fp = fopen(path, "r");
             if (NULL != fp)
             {
                 if( fgets(buf, BUF_SIZE-1, fp)== NULL ){
                     fclose(fp);
                     continue;
                 }
                 sscanf(buf, "%*s %s", cur_task_name);
         
                 //如果文件内容满足要求则打印路径的名字（即进程的PID）
                 if (strstr(cur_task_name, task_name)){
                     sscanf(ptr->d_name, "%ls", res[i]);
                     i++;
                 }
                 fclose(fp);
             }
         }
         closedir(dir);
     
    }
    res[i] = 0;
    return res;
}

char** kdk_procname_get_process_infomation(char *proc_name)
{
    int **pid = getPidByName(proc_name);
    int index = 0;
    char **res = NULL;
    int **ret = realloc(res, sizeof(int)*PROC_COMD_NUM);
    res = ret;
    char *tmp = (char *)malloc(PROC_COMD_NUM*sizeof(char));
    char *proc = (char *)malloc(PROC_COMD_NUM*sizeof(char));
    float percent = 0.00;
    int proc_pid = 0;
    int num = 0;
    char *result = (char *)malloc(PROC_COMD_NUM*sizeof(char));
    while (pid[index])
    {
        sprintf(proc, "%ls", pid[index]);
        proc_pid = atoi(proc);
        res[index] = malloc(sizeof(int) * PROC_COMD_NUM);
        memset(result,0,PROC_COMD_NUM*sizeof(char));
        strcat(result,"proc_pid:"); 
        sprintf(tmp, "%d", proc_pid);
        strcat(result,tmp);
        strcat(result,", ");
        percent = kdk_get_process_cpu_usage_percent(proc_pid);
        strcat(result,"proc_cpu:"); 
        sprintf(tmp, "%0.1f", percent);
        strcat(result,tmp);
        strcat(result,", ");
        percent = kdk_get_process_mem_usage_percent(proc_pid);
        strcat(result,"proc_mem:");
        sprintf(tmp, "%0.1f", percent);
        strcat(result,tmp);
        strcat(result,", ");
        tmp = kdk_get_process_status(proc_pid);
        strcat(result,"proc_state:");
        strcat(result,tmp);
        strcat(result,", ");
        num = kdk_get_process_port(proc_pid);
        strcat(result,"proc_port:");
        sprintf(tmp, "%d", num);
        strcat(result,tmp);
        strcat(result,", ");
        tmp = kdk_get_process_start_time(proc_pid);
        strcat(result,"start_time:");
        strcat(result,tmp);
        strcat(result,", ");
        tmp = kdk_get_process_running_time(proc_pid);
        strcat(result,"proc_time:");
        strcat(result,tmp);
        strcat(result,", ");
        tmp = kdk_get_process_cpu_time(proc_pid);
        strcat(result,"utime:");
        strcat(result,tmp);
        strcat(result,", ");
        tmp = kdk_get_process_command(proc_pid);
        strcat(result,"proc_command:");
        strcat(result,tmp);
        strcat(result,", ");
        tmp = kdk_get_process_user(proc_pid);
        strcat(result,"proc_uid:");
        strcat(result,tmp);
        strcat(result,", ");

        strcpy(res[index], result);
        index++;
    }
    kdk_proc_freeall(pid);
    res[index] = NULL;
    free(tmp);
    free(proc);
    free(result);
    return res;
}

static int get_proc_name(pid_t pid, char *name)
{
	FILE *fpprocstat;
	char procstatf[128] = {0};
	char line[128] = {0};
	char *start, *end;
	char *buf = NULL;
	int num;

	if (pid < 0)
		return -1;
	else
		sprintf (procstatf, "/proc/%d/stat", pid);
	if (strstr(procstatf, ".."))
		return -1;

	if ((fpprocstat = fopen(procstatf, "r")) == NULL) {
		//fclose(fpprocstat);
		return -1;
	}

	buf = fgets(line, sizeof(line), fpprocstat);
	line[strlen(line) + 1] = '\0';
	start = strchr(line, '(') + 1;
	end = strrchr(start, ')');
	num = end - start;
	strlcpy(name, start, num + 1);
	fclose(fpprocstat);

	return 0;
}

int get_proc_state(pid_t pid, char *state)
{
	FILE *fpprocstat;
	char procstatf[128] = {0};
	char line[128] = {0};
    char *name = NULL;

	if (pid < 0 )
		return -1;
	else
		sprintf (procstatf, "/proc/%d/status", pid);

	if (strstr(procstatf, "../"))
		return -1;

	if ((fpprocstat = fopen(procstatf, "r")) == NULL) {
		//fclose(fpprocstat);
		return -1;
	}

	while (fgets(line, sizeof(line), fpprocstat) != NULL) {
		if (lookup(line, "State", &name))
            break;
	}
	fclose(fpprocstat);
    strcpy(state, name);

	return 0;
}

static int get_proc_command(pid_t pid, char *command)
{
	FILE *fd;
	char path[128] = {0};

	if (pid < 0 )
		return -1;
	else
		sprintf(path, "/proc/%d/cmdline", pid);

	if (strstr(path, "../"))
		return -1;

	if ((fd = fopen(path, "r")) == NULL) {
		return -1;
	}
	int c;
	int i =0;
	while(1) {
		char a = ' ';

		c = fgetc(fd);
		if (feof(fd))
			break;
		if (c == '\0')
			command[i] = a;
		else
			command[i] = c;
		i++;
	}

	fclose(fd);

	return 0;
}

int get_proc_uid(pid_t pid, char *proc_uid)
{
	FILE *fpprocstat, *fp;
	char procstatf[128] = {0};
	char line[128] = {0};
    char buff[128] = {0};
    char *name = NULL;
    int j = 0, i = 0;
    char *bufs[10], *q = NULL;
    char *buf[5], *p = NULL;

    sprintf (procstatf, "/proc/%d/status", pid);


	if ((fpprocstat = fopen(procstatf, "r")) == NULL)
		return -1;

	while (fgets(line, sizeof(line), fpprocstat) != NULL) {
		if (lookup(line, "Uid", &name))
            break;
	}

	p = strtok(name, "	");
	while(p)
	{
		buf[i] = p;
		i++;
		p = strtok(NULL,"	");
	}
    if ((fp = fopen("/etc/passwd", "r")) == NULL)
		return -1;

	while (fgets(buff, sizeof(buff), fp) != NULL) {
		if(strstr(buff, buf[1]))
        {
            q = strtok(buff, ":");
            while(q)
            {
                bufs[j] = q;
                j++;
                q = strtok(NULL,":");
            }
            
            if(!strcmp(buf[1],bufs[2]))
            {
                strcpy(name, bufs[0]);
                break;
            }
        }
	}
    strcpy(proc_uid, name);

	fclose(fpprocstat);
    fclose(fp);

	return 0;
}

int get_proc_mem_usage_pct (const pid_t pid, double *pct)
{
	FILE *fpmeminfo;
	FILE *fpprocstat;
	long memtotal = 1;
	long memproc = 0;
	char procstatf[128] = {0};
	char line[128] = {0};

	if (pid <= 0)
		return -1;

	if ((fpmeminfo = fopen(MEMINFO, "r")) == NULL)
		return -1;

	while (fgets(line, sizeof(line), fpmeminfo) != NULL) {
		if (!strncmp(line, "MemTotal:", 9)) {
			sscanf(line + 9, "%ld", &memtotal);
			break;
		}
	}
	fclose(fpmeminfo);

	if (pid < 0 )
		return -1;
	else
		sprintf (procstatf, "/proc/%d/status", pid);

	if (strstr(procstatf, "../"))
		return -1;

	if ((fpprocstat = fopen(procstatf, "r")) == NULL)
		return -1;

	while (fgets(line, sizeof(line), fpprocstat) != NULL) {
		if (!strncmp(line, "VmRSS:", 6)) {
			sscanf(line + 6, "%lu", &memproc);
			break;
		}
	}

	fclose(fpprocstat);

	*pct = 100 * memproc / (double)memtotal;
	return 0;
}

int get_proc_starttime(pid_t pid, char *start_time)
{
	char stat_filepath[30] = {0};
	char *t = NULL;
	char tt[1024] = {0};
	unsigned long long time1, starttime;
	char *st = NULL;

	if (pid < 0 )
		return -1;
	else
		sprintf (stat_filepath, "/proc/%d/stat", pid);

	if (strstr(stat_filepath, "../"))
		return -1;

	FILE *fpstat = fopen(stat_filepath, "r");
	if (fpstat == NULL) {
		perror("FOPEN ERROR ");
		return -1;
	}

	t = fgets(tt, sizeof(tt), fpstat);
	if (sscanf(t , "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %*u %*u %*d %*d %*d %*d %*d %*d %19llu %*u", &time1) == EOF) {
		fclose(fpstat);
		return -1;
	}
	fclose(fpstat);

	time_t now;
	now = time(NULL);
	struct timespec time2 = {0, 0};
	clock_gettime(CLOCK_MONOTONIC, &time2);

	starttime = (unsigned long long)(time1/HZ) + (now - time2.tv_sec);
	time_t time3 = starttime;
	st = (char *)calloc(128, sizeof(char));

	st = ctime(&time3);
	strncpy(start_time, st, 128);
	// free(st);

	return 0;
}

static unsigned long get_proc_cpu_time (pid_t pid)
{
	char stat_filepath[30] = {0};
	struct pstat result;
	unsigned long utime = 0;

	if (pid < 0 )
		return -1;
	else
		sprintf (stat_filepath, "/proc/%d/stat", pid);

	if (strstr(stat_filepath, "../"))
		return -1;

	FILE *fpstat = fopen(stat_filepath, "r");
	if (fpstat == NULL) {
		perror("FOPEN ERROR ");
		return -1;
	}

	bzero(&result, sizeof(struct pstat));

	if (fscanf(fpstat, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu %*s",
		   &result.utime_ticks, &result.stime_ticks) == EOF) {
		fclose(fpstat);
		return -1;
	}

	utime = (long)((result.utime_ticks + result.stime_ticks)/HZ);
	fclose(fpstat);

	return utime;
}

int get_proc_cpu_pcpu (pid_t pid, double *pcpu)
{
	char stat_filepath[30] = {0};
	struct pstat result;
	unsigned long long time1;
	long cutime,cstime;
	*pcpu = 0;

	if (pid < 0 )
		return -1;
	else
		sprintf (stat_filepath, "/proc/%d/stat", pid);

	if (strstr(stat_filepath, "../"))
		return -1;

	FILE *fpstat = fopen(stat_filepath, "r");
	if (fpstat == NULL) {
		perror("FOPEN ERROR ");
		return -1;
	}

	bzero(&result, sizeof(struct pstat));
	if (fscanf(fpstat, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu %lu %lu %*d %*d %*d %*d %llu %*u",
		   &result.utime_ticks, &result.stime_ticks, &cutime, &cstime, &time1 )== EOF) {
		fclose(fpstat);
		return -1;
	}

	struct timespec time2 = {0, 0};
	clock_gettime(CLOCK_MONOTONIC, &time2);

	long long t1, t2;
	t1 = (result.utime_ticks + result.stime_ticks)/HZ;
	t2 = time2.tv_sec - time1/HZ;

	if (t2)
		*pcpu = (double)(100 * t1/t2);
	fclose(fpstat);

	return 0;
}

int get_proc_running_time(pid_t pid, char *proc_time)
{
    char path[100] = {0};
	char *t = NULL;
	char tt[1024] = {0};
	unsigned long long time1, starttime;
	char *st = NULL;
    unsigned long long seconds;

    sprintf(path, "/proc/%d/stat", pid);
	FILE *fpstat = fopen(path, "r");
	if (fpstat == NULL) {
		return -1;
	}

	t = fgets(tt, sizeof(tt), fpstat);
	if (sscanf(t , "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %*u %*u %*d %*d %*d %*d %*d %*d %19llu %*u", &time1) == EOF) {
		fclose(fpstat);
		return -1;
	}
	fclose(fpstat);
    
    time_t seconds_since_boot    = uptime(0,0);
    seconds = seconds_since_boot - (time1/100);
    char *restrict const outbuf;
    
    unsigned dd,hh,mm,ss;
    char *cp = (char *)calloc(128, sizeof(char));
    char *buff = (char *)calloc(128, sizeof(char));
    ss = seconds%60;
    seconds /= 60;
    mm = seconds%60;
    seconds /= 60;
    hh = seconds%24;
    seconds /= 24;
    dd = seconds;
    if(dd)
    {
        snprintf(cp, COLWID, "%u-", dd);
    }else{
        snprintf(cp, COLWID, "%u-", 0);
    }
    if(dd || hh)
    {
        snprintf(buff, COLWID, "%02u:", hh);
        strcat(cp, buff);
    }
    else{
        snprintf(buff, COLWID, "%02u:", 0);
        strcat(cp, buff);
    }
    memset(buff,'\0',sizeof(buff));
    snprintf(buff, COLWID, "%02u:%02u", mm, ss);
    strcat(cp, buff);
    strcpy(proc_time, cp);
    free(buff);
    return 0;
}

int get_proc_port(pid_t pid, char *proc_prot)
{
    unsigned long rxq, txq, time_len, retr, inode;
    int num, local_port, rem_port, d, state, uid, timer_run, timeout;
    char rem_addr[128], local_addr[128], timers[64];
	char file_name[100] = {0};
	FILE *fd;
	char line_buff[1024]={0};
    char line[LINE_MAX];
    int lnamelen;
    char lname[30];
    unsigned long inode_num;
    DIR *dirfd = NULL;
    struct dirent *direproc, *direfd;
    char path[100] = {0};
    sprintf(path, "/proc/%d/fd", pid);

	dirfd = opendir(path);
    if (! dirfd) {
	    return 0;
	}
	while ((direfd = readdir(dirfd))) {
        sprintf(line, "/proc/%d/fd/%s", pid, direfd->d_name);
	    lnamelen = readlink(line, lname, sizeof(lname) - 1);
	    if (lnamelen == -1)
		    continue;
        lname[lnamelen] = '\0';  /*make it a null-terminated string*/

        if (extract_type_1_socket_inode(lname, &inode_num) < 0)
            if (extract_type_2_socket_inode(lname, &inode_num) < 0)
                continue;
        fd = fopen("/proc/net/tcp","r");
        if(NULL == fd){
            return 0;
        }
        
        while(fgets(line_buff,sizeof(line_buff),fd))
        {
            num = sscanf(line_buff,
            "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %lu %*s\n",
                    &d, local_addr, &local_port, rem_addr, &rem_port, &state,
                    &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode);
            if(inode_num == inode)
            {
                sprintf(proc_prot, "%d", local_port);
            }else
            {
                continue;
            }
        }
    }
    return 0;
}

int get_process_info(process_info *info, unsigned int *proc_num)
{
	DIR *dir;
	FILE *fp;
	struct  dirent *drd;
	struct stat buf;
	process_info *proc_info = info;
	char filename[MAX_PF_NAME];
	char dirname[MAX_PF_NAME];

	int count = 0;
	*proc_num = 0;
	if ((dir = opendir(PROC_DIR)) == NULL)
		return -1;

	while ((drd = readdir(dir)) != NULL){
		if (*proc_num >= MAX_PROC_NUM)
			break;
		if (isnumber(drd->d_name)){
			sprintf(dirname, "%s/%s", PROC_DIR, drd->d_name);
			if (stat(dirname, &buf) < 0)
				continue;
			if (!S_ISDIR(buf.st_mode))
				continue;

			memset (proc_info, 0, sizeof(process_info));
			sprintf(filename, "%s/%s/stat", PROC_DIR, drd->d_name);
			if ((fp = fopen(filename, "r")) == NULL) {
				//fclose(fp);
				continue;
			}
			fclose(fp);
			sscanf(drd->d_name, "%ld", &(proc_info->proc_pid));
			if (get_proc_name(proc_info->proc_pid, proc_info->proc_name) < 0)
				continue;
            
			if (get_proc_state(proc_info->proc_pid, &(proc_info->proc_state)) <0)
				continue;
            
			if (get_proc_command(proc_info->proc_pid, proc_info->proc_command) < 0)
				continue;
            
			if (get_proc_uid(proc_info->proc_pid, proc_info->proc_uid) < 0)
				continue;
            
			if (get_proc_mem_usage_pct(proc_info->proc_pid, &(proc_info->proc_mem)) < 0)
				continue;
            
			if (get_proc_starttime(proc_info->proc_pid, proc_info->start_time) < 0)
				continue;
            
			proc_info->utime = get_proc_cpu_time(proc_info->proc_pid);
			if (proc_info->utime < 0)
				continue;

			if (get_proc_cpu_pcpu(proc_info->proc_pid, &(proc_info->proc_cpu)) < 0)
				continue;

            if (get_proc_running_time(proc_info->proc_pid, proc_info->proc_time) < 0)
				continue;

            if (get_proc_port(proc_info->proc_pid, proc_info->proc_port) < 0)
				continue;

			proc_info++;
			(*proc_num)++;
			++count;
		}
        
	}
	closedir(dir);

	return 0;
}

char** kdk_get_process_all_information()
{
    process_info pp[PROC_NUM];
    unsigned int proc_num;
    char * result;
    char *tmp;
    size_t counts = 0;
    result = (char *)malloc(115200*sizeof(char));
    tmp = (char *)malloc(115200*sizeof(char));
    // memset(result,0,4096*sizeof(char));
    char **res = NULL;
    int ret = get_process_info(pp, &proc_num);
    if(ret==0){
        for(int i=0;i<proc_num;i++){
            memset(result,0,115200*sizeof(char));
            strcat(result,"process_id:");
            sprintf(tmp,"%ld",pp[i].proc_pid);   
            strcat(result,tmp);
            strcat(result,", ");
            // printf("进程id:%ld\n", pp[i].proc_pid);  
            strcat(result,"proc_name:");
            strcat(result,pp[i].proc_name);
            strcat(result,", ");
            // printf("进程名称：%s\n", pp[i].proc_name);
            strcat(result,"proc_command:");
            strcat(result,pp[i].proc_command);
            strcat(result,", ");
            // printf("进程启动的命令行:%s\n", pp[i].proc_command);
            strcat(result,"proc_uid:");
            sprintf(tmp,"%s",pp[i].proc_uid);   
            strcat(result,tmp);
            strcat(result,", ");
            // printf("进程所属用户:%s\n",pp[i].proc_uid);
            strcat(result,"start_time:");
            strcat(result,pp[i].start_time);
            strcat(result,", ");
            // printf("进程创建时间:%s", pp[i].start_time);
            strcat(result,"utime:");
            sprintf(tmp,"%ld",pp[i].utime);   
            strcat(result,tmp);
            strcat(result,", ");
            // printf("进程cpu使用时间:%ld\n", pp[i].utime);
            strcat(result,"proc_cpu:");
            sprintf(tmp,"%.2f",(double)pp[i].proc_cpu);   
            strcat(result,tmp);
            strcat(result,", ");
            // printf("进程cpu使用率:%.2f\n", (double)pp[i].proc_cpu);
            strcat(result,"proc_mem:");
            sprintf(tmp,"%.2f",(double)pp[i].proc_mem);   
            strcat(result,tmp);
            strcat(result,", ");
            // printf("进程使用内存量:%.2f\n", (double)pp[i].proc_mem);
            strcat(result,"proc_state:");
            sprintf(tmp,"%s",pp[i].proc_state);   
            strcat(result,tmp);
            strcat(result,", ");
            // printf("进程状态:%d\n", pp[i].proc_state);
            strcat(result,"proc_time:");
            sprintf(tmp,"%s",pp[i].proc_time);   
            strcat(result,tmp);
            strcat(result,", ");
            // printf("进程运行时间:%d\n", pp[i].proc_time);
            strcat(result,"proc_port:");
            sprintf(tmp,"%s",pp[i].proc_port);   
            strcat(result,tmp);
            // printf("进程端口号:%s\n", pp[i].proc_port);

            res = realloc(res, (counts + 3) * sizeof(char *));

            res[counts] = malloc(115200 * sizeof(char) + 1);
            strcpy(res[counts], result);
            counts++;
        }
    }
    res[counts] = NULL;
    return res;
}

inline void kdk_proc_freeall(char **list)
{
    if (! list)
        return;
    size_t index = 0;
    while (list[index])
    {
        free(list[index]);
        index ++;
    }
    free(list);
}